home *** CD-ROM | disk | FTP | other *** search
/ Apple II Magazines (PO) / Nibble Volume 11, No. 04 - 05 - 06 (1990)(MindCraft Publishing)[no boot].zip / Nibble Volume 11, No. 04 - 05 - 06 (1990)(MindCraft Publishing)[no boot].po / NIBBLE.1990:APR.VOL11.NO04 / PRODOS.LINKER.S < prev    next >
Text File  |  1996-12-24  |  24KB  |  767 lines

  1. ********************************
  2. * PRODOS.LINKER Source Code    *
  3. * by Mark Hadley               *
  4. * Copyright (c) 1990           *
  5. * MondCraft Publ. Corp.        *
  6. * Concord, MA  01742           *
  7. ********************************
  8.  
  9. * MINDCRAFT ASSEMBLER -- converted to Merlin-8
  10.  
  11. * ProDOS Equates
  12.  
  13. EXTRNCMD  EQU $BE06      ; External cmd JMP instruction
  14. ERROUT    EQU $BE09      ; Error handler
  15. XTRNADDR  EQU $BE50      ; Start of external cmd handler
  16. XLEN      EQU $BE52      ; External cmd name length (-1)
  17. XCNUM     EQU $BE53      ; Command # (0 for external)
  18. PBITS     EQU $BE54      ; Command parameter bits
  19. FBITS     EQU $BE56      ; Parameters found in pares
  20. APARM     EQU $BE58      ; Address parameter specified
  21. SPARM     EQU $BE61      ; Slot parameter specified
  22. DPARM     EQU $BE62      ; Drive parameter specified
  23. GETBUFR   EQU $BEF5      ; Get free space
  24. MLI       EQU $BF00      ; Machine Language Interface
  25. BITMAP    EQU $BF58      ; Protected memory locations
  26.  
  27. * variables
  28.  
  29. DESTPTR   EQU $00        ; ZP pointer for prgm dest
  30. TSPTR     EQU $02        ; ZP pointer for T/S list
  31. DATAPTR   EQU $04        ; ZP pointer for data
  32.  
  33. FLNMLEN   EQU $250       ; Length of filename
  34. YTEMP     EQU $251       ; Save Y-reg
  35. CMD       EQU $252       ; Command (0-DLOAD, 1-DBLOAD)
  36. TRACK     EQU $253       ; Track to read from
  37. SECTOR    EQU $254       ; Sector to read from
  38. LENGTH    EQU $255       ; Length of file
  39. PARMTBL   EQU $257       ; Beginning of parameter table
  40. UNITNUM   EQU $258       ; Code for slot/drive
  41. BUFFER    EQU $259       ; Pointer to buffer to load at
  42. BLOCK     EQU $25B       ; Block to load from disk
  43. FILENAME  EQU $25D       ; Name of file to load
  44.  
  45. * Other equates:
  46.  
  47. A1L       EQU $3C        ; Beginning addr of move
  48. A2L       EQU $3E        ; Ending addr of move
  49. A4L       EQU $42        ; Destination of move
  50. TXTTAB    EQU $67        ; Start of Applesoft program
  51. VARTAB    EQU $69        ; Start of simple variable space
  52. HIMEM     EQU $73        ; Start of ProDOS buffer
  53. PRGEND    EQU $AF        ; End of Applesoft program
  54.  
  55. IN        EQU $200       ; Input buffer
  56.  
  57. KBD       EQU $C000      ; Keypress input
  58. KBSTROBE  EQU $C010      ; Key-pressed status
  59.  
  60. LINPRT    EQU $ED24      ; Prints 16 bit hex as decimal
  61. CROUT     EQU $FD8E      ; Output a carriage return
  62. COUT      EQU $FDED      ; Output a character in Acc
  63. MOVE      EQU $FE2C      ; Move block of memory
  64.  
  65.           ORG $2000
  66.  
  67. * Resetve space for commands
  68.  
  69.           SEC            ; Calcuate # pages to reserve
  70.           LDA #>END100
  71.           SBC #>BEGIN
  72.           STA PAGES
  73.           JSR GETBUFR    ; Open room for commands
  74.           BCC INSTALL
  75.           LDA #14        ; BASIC error: prgm too large
  76.           JMP ERROUT     ; Print error msg and quit
  77.  
  78. INSTALL   STA PGSTART    ; Addr of freed space
  79.           LDA EXTRNCMD+1 ; Must create link to
  80.           STA NEXTCMD+1  ;  any existing external
  81.           LDA EXTRNCMD+2 ;  commands
  82.           STA NEXTCMD+2
  83.  
  84.           LDA #0         ; Install commands
  85.           STA EXTRNCMD+1 ;  by storing the command
  86.           LDA PGSTART    ;  handler address at
  87.           STA EXTRNCMD+2 ;  EXTRNCMD
  88.  
  89. * Protect memory from ProDOS operations
  90.  
  91.           LDA PGSTART
  92.           STA PRTCTPG    ; Starting page to protect
  93. PROTECT   LDA PRTCTPG    ; Get page to protect
  94.           JSR SETBIT
  95.           INC PRTCTPG
  96.           DEC PAGES      ; Finished with all pages?
  97.           BNE PROTECT    ;  No, keep going.
  98.  
  99. * Relocate the command code
  100.  
  101.           LDX #0
  102.           LDA PGSTART    ; Get the new page number
  103.           SEC
  104.           SBC #>BEGIN    ; Offset to new location
  105.           STA OFFSET
  106.           LDA #<BEGIN    ; Search for cmds to relocate
  107.           STA $FE
  108.           LDA #>BEGIN
  109.           STA $FF
  110.           LDY #0
  111. RELOC1    LDA ($FE),Y
  112.           CMP #$D9       ; CMP command?
  113.           BEQ RELOC3
  114.           CMP #$20       ; JSR command?
  115.           BEQ RELOC3
  116.           CMP #$4C       ; JMP command?
  117.           BEQ RELOC3
  118.           CMP #$B9       ; LDA command?
  119.           BEQ RELOC3
  120.           CMP #$BD       ; LDA,X command?
  121.           BEQ RELOC3
  122.           INC $FE
  123.           BNE RELOC2
  124.           INC $FF
  125. RELOC2    LDA $FF
  126.           CMP #>END100
  127.           BNE RELOC1
  128.           JMP RELOC4
  129. RELOC3    CLC
  130.           LDA $FE
  131.           ADC #2
  132.           STA $FE
  133.           LDA $FF
  134.           ADC #0
  135.           STA $FF
  136.           LDA ($FE),Y
  137.           CMP #>BEGIN    ; Within bounds of program?
  138.           BCC RELOC2     ; No, so don't change
  139.           CMP #>END100
  140.           BCS RELOC2     ; No, so don't change
  141.           ADC OFFSET     ; Yes, change it
  142.           STA ($FE,X)
  143.           JMP RELOC2     ;  and continue
  144. RELOC4    LDA #>BEGIN
  145.           STA $FF
  146.           LDA #<BEGIN
  147.           STA $FE
  148. RELOC5    LDA ($FE),Y
  149.           CMP #$A9       ; LDA command?
  150.           BEQ RELOC7
  151. RELOC6    INC $FE
  152.           BNE RELOC5
  153.           BEQ RELOC8
  154. RELOC7    INC $FE
  155.           LDA ($FE),Y
  156.           CMP #>BEGIN    ; First page of program?
  157.           BCC RELOC6     ; No, don't change it
  158.           CMP #>END100   ; Less than last page?
  159.           BCS RELOC7     ; No, don't change it
  160.           ADC OFFSET     ; Yes, change to new place
  161.           STA ($FE),Y
  162.           JMP RELOC6     ; and continue looking...
  163. RELOC8    EQU *
  164.  
  165. * Move the code to final position
  166.  
  167.           LDA #<BEGIN
  168.           STA A1L
  169.           LDA #>BEGIN
  170.           STA A1L+1
  171.           LDA #<END
  172.           STA A2L
  173.           LDA #>END
  174.           STA A2L+1
  175.           LDA #0
  176.           STA A4L
  177.           LDA PGSTART
  178.           STA A4L+1
  179.           LDY #0
  180.           JSR MOVE       ; Move the code and exit
  181.  
  182. * Announce successful installation
  183. * and display commands and parameters
  184.  
  185.           LDY #0
  186. MSGOUT    LDA MSG,Y      ; Get next character
  187.           JSR COUT       ;  and print it
  188.           INY
  189.           CPY #MSGEND-MSG ; Finished?
  190.           BNE MSGOUT     ; Nope, keep going.
  191.           RTS            ;  Yes, installation complete
  192.  
  193. SETBIT    PHA            ; Acc holds high addr byte
  194.           AND #$07       ;  of memory page to protect
  195.           TAX
  196.           PLA
  197.           LSR            ; Upper five bits of Acc
  198.           LSR            ;  make an index into
  199.           LSR            ;  the bit map
  200.           TAY
  201.           LDA #0         ; Lower 3 bits of Acc
  202.           SEC            ;  choose the bit to
  203. SETLP     ROR            ;  be set.  X-reg counts
  204.           DEX            ;  while bit is shifted into
  205.           BPL SETLP      ;  place from carry
  206.           ORA BITMAP,Y
  207.           STA BITMAP,Y   ; Set the bit in bit map
  208.           RTS
  209.  
  210. PAGES     DS 1           ; Length of command handler
  211. PGSTART   DS 1           ; Start of command handler
  212. OFFSET    DS 1           ; Offset to new location
  213. PRTCTPG   DS 1           ; Next page to protect
  214.  
  215. MSG       HEX 8D8D
  216.           ASC "ProDOS Linker Installed"
  217.           HEX 8D
  218.           ASC "COMMANDS:"
  219.           HEX 8D
  220.           ASC "DLOAD <NAME>[,S#][,D#]"
  221.           HEX 8D
  222.           ASC "DBLOAD <NAME>[,S#][,D#][,A ADDR]"
  223.           HEX 8D
  224.           ASC "DCAT [,S#][,D#]"
  225.           HEX 8D8D
  226. MSGEND    EQU *
  227.           DS $2200-*     ; (Fill 0's to page boundary)
  228.  
  229. BEGIN     EQU *
  230.  
  231. ********************************
  232.  
  233. * Check for commands
  234.  
  235.           CLD            ; Req'd as I.D. for external cmd
  236.           LDY #0
  237.           LDX #0
  238. CHKCMD    LDA IN,X       ; Get command character
  239.           INX
  240.           CMP #$A0       ; Is it a blank?
  241.           BEQ CHKCMD     ; If it is, ignore it
  242.           CMP DLNAME,Y   ; Same as DLOAD?
  243.           BEQ CHKCMD1    ;  Yes, continue to end
  244.           CMP #$E0       ; Lower case?
  245.           BCC NOTFOUND1  ;  No, so try next
  246.           AND #$DF       ;  Yes, convert to uppercase
  247.           CMP DLNAME,Y   ; OK now?
  248.           BNE NOTFOUND1  ;  No, so try next
  249. CHKCMD1   INY
  250.           CPY #DLLEN-DLNAME ; At end?
  251.           BNE CHKCMD     ; No, so continue
  252.           BEQ DLOAD      ; Yes, so DLOAD requested
  253. NOTFOUND1 LDY #0         ; Try next command
  254.           LDX #0
  255. CHKCMD2   LDA IN,X
  256.           INX
  257.           CMP #$A0
  258.           BEQ CHKCMD2
  259.           CMP DBNAME,Y
  260.           BEQ CHKCMD3
  261.           CMP #$E0
  262.           BCC NOTFOUND2
  263.           AND #$DF
  264.           CMP DBNAME,Y
  265.           BNE NOTFOUND2
  266. CHKCMD3   INY
  267.           CPY #DBLEN-DBNAME
  268.           BNE CHKCMD2
  269.           BEQ DBLOAD     ; DBLOAD requested
  270. NOTFOUND2 LDY #0
  271.           LDX #0
  272. CHKCMD4   LDA IN,X       ; Get command character
  273.           INX
  274.           CMP #$A0       ; Is it a blank?
  275.           BEQ CHKCMD4    ; If it is, ignore it
  276.           CMP DCNAME,Y   ; Save as DCAT?
  277.           BEQ CHKCMD5    ;  Yes, continue to end
  278.           CMP #$E0       ; Lower case?
  279.           BCC NOTFOUND3  ;  No, so exit
  280.           AND #$DF       ;  Yes, convert to uppercase
  281.           CMP DCNAME,Y   ; OK now?
  282.           BNE NOTFOUND3  ;  No, so exit
  283. CHKCMD5   INY
  284.           CPY #DCLEN-DCNAME ; At end?
  285.           BNE CHKCMD4    ; No, so continue
  286.           BEQ DCAT       ; Yes, so DCAT requested
  287. NOTFOUND3 SEC            ; Set carry to indicate failure
  288. NEXTCMD   JMP $0000      ; Jump to next external cmd
  289.  
  290. DLOAD     JSR GETNAME    ; Get filename after cmd
  291.           LDA #$00
  292.           STA XCNUM      ; Extername cmd number = 0
  293.           LDA #<EXECUTE  ; Store return address
  294.           STA XTRNADDR   ;  for BASIC.SYSTEM
  295.           LDA #>EXECUTE
  296.           STA XTRNADDR+1
  297.  
  298. * Set up parsing rules for DLOAD
  299.  
  300.           LDA #$10       ; Pathname is not required
  301.           STA PBITS
  302.           LDA #$04       ; Allow slot and drive parms
  303.           STA PBITS+1
  304.           LDA #$00
  305.           STA CMD        ; DLOAD command active
  306.           CLC            ; Command recognized
  307.           RTS            ; Let BASIC.SYSTEM do parsing
  308.  
  309. DBLOAD    JSR GETNAME    ; Get filename after cmd
  310.           LDA #0
  311.           STA XCNUM      ; Externale cmd number = 0
  312.           LDA #<EXECUTE  ; Set return address
  313.           STA XTRNADDR   ;  for BASIC SYSTEM
  314.           LDA #>EXECUTE
  315.           STA XTRNADDR+1
  316.  
  317. * Set up parsing rules
  318.  
  319.           LDA #$10       ; Pathname not required
  320.           STA PBITS
  321.           LDA #$84       ; Address, Slot, Drive parms
  322.           STA PBITS+1    ;  allowed
  323.           LDA #$01
  324.           STA CMD        ; DBLOAD command active
  325.           CLC            ; Command recognized
  326.           RTS            ; Let BASIC.SYSTEM do parsing
  327.  
  328. DCAT      DEY            ; Length of command
  329.           STY XLEN
  330.           LDA #0
  331.           STA XCNUM      ; External cmd number = 0
  332.           LDA #<EXECAT   ; Set return address
  333.           STA XTRNADDR   ;  for BASIC.SYSTEM
  334.           LDA #>EXECAT
  335.           STA XTRNADDR+1
  336.  
  337. * Set parsing rules for DCAT
  338.  
  339.           LDA #$10       ; Pathname not required
  340.           STA PBITS
  341.           LDA #$04       ; Slot, Drive parms allowed
  342.           STA PBITS+1
  343.           CLC            ; Command recognized
  344.           RTS            ; Let BASIC.SYSTEM do parsing
  345.  
  346. * Find filename in DIS 3.3 directory
  347.  
  348. EXECUTE   JSR SETPARMS   ; Set up MLI parameters
  349.           JSR CHECKPRO   ; Check for ProDOS disk
  350.           LDA #3         ; Set # parms for READ_BLOCK
  351.           STA PARMTBL
  352.           LDA #$11       ; Track containing DOS directory
  353.           STA TRACK
  354.           LDA #$0F       ; Sector of directory start
  355.           STA SECTOR
  356. NEXTDIR   CLC            ; Load in data buffer
  357.           JSR READTS     ; Get start of directory
  358.           LDA #$0B       ; Position of first entry
  359.           STA DATAPTR
  360. NXTENTRY  LDY #0         ; Track of t/x list
  361.           LDA (DATAPTR),Y
  362.           CMP #$FF       ; If file is deleted, skip it
  363.           BEQ NOTFILE
  364.           LDY #3         ; Start of filename
  365.           LDX #0
  366. CHKFLNM   LDA (DATAPTR),Y
  367.           CMP FILENAME,X
  368.           BNE NOTFILE
  369.           INY
  370.           INX
  371.           CPX FLNMLEN
  372.           BCC CHKFLNM
  373.           CPX #30        ; If filename 30 chars ling
  374.           BEQ GOTFILE    ;  then file is correct one
  375.           LDA (DATAPTR),Y ; If next character is space,
  376.           CMP #$A0       ;  then file is correct one
  377.           BEQ GOTFILE
  378. NOTFILE   CLC
  379.           LDA DATAPTR
  380.           ADC #$23       ; Move to next entry
  381.           STA DATAPTR
  382.           BCC NXTENTRY
  383.           LDY #0         ; Must get next sector
  384.           LDA #1
  385.           STA DATAPTR
  386.           LDA (DATAPTR),Y ; Track of next directory
  387.           BEQ FLNOTFND   ; If 0, then no such file
  388.           STA TRACK
  389.           INY
  390.           LDA (DATAPTR),Y ; Sector of next directory
  391.           STA SECTOR
  392.           BPL NEXTDIR    ; Always branch
  393. FLNOTFND  LDA #7         ; BASIC error: path not found
  394.           SEC            ; Flag error
  395.           RTS            ; Let BASIC.SYSTEM report error
  396.  
  397. * File found, make sure it si right type
  398.  
  399. GOTFILE   LDY #2         ; Location of file type
  400.           LDA (DATAPTR),Y
  401.           AND #$0F       ; Remove locked indicator
  402.           LDX CMD        ; Looking for Applesoft file?
  403.           BEQ CHKAPLS    ;  Yes, so branch
  404.           CMP #4         ; check for Binary file
  405.           BEQ TYPEOK     ; File is correct type
  406. BADTYPE   LDA #$0D       ; BASIC err: file type mismatch
  407.           SEC            ; Flag error
  408.           RTS            ; Let BASIC.SYSTEM report error
  409. CHKAPLS   CMP #2         ; Check for Applesoft file
  410.           BNE BADTYPE    ; Error if not right
  411. TYPEOK    EQU *          ; Type is what we're looking for
  412.  
  413. * Find and load file's T/S sector
  414.  
  415.           LDY #0         ; Track of file's T/S
  416.           LDA (DATAPTR),Y
  417.           STA TRACK
  418.           INY            ; Sector of file's T/S
  419.           LDA (DATAPTR),Y
  420.           STA SECTOR
  421.           SEC            ; Load into T/S buffer
  422.           JSR READTS
  423.  
  424. * Load file's first data sector
  425.  
  426.           LDY #$0C       ; Track of first file sector
  427.           LDA (TSPTR),Y
  428.           STA TRACK
  429.           INY            ; Sector of first file sector
  430.           LDA (TSPTR),Y
  431.           STA SECTOR
  432.           INY
  433.           STY YTEMP
  434.           CLC            ; Load to data buffer
  435.           JSR READTS     ; Get the first sector
  436.           LDA CMD        ; Working on Applesoft file?
  437.           BEQ APLSOFT    ;  Yes, so branch
  438.           LDY #0         ; Find where file goes
  439.           LDA (DATAPTR),Y
  440.           STA DESTPTR
  441.           INY
  442.           LDA (DATAPTR),Y
  443.           STA DESTPTR+1
  444.           LDA FBITS+1    ; Now check if addr specified
  445.           BPL ADDROK     ;  Not specified
  446.           LDA APARM      ;  Specified, so get it
  447.           STA DESTPTR
  448.           LDA APARM+1
  449.           STA DESTPTR+1
  450. ADDROK    INY            ; Location of file length
  451.           LDA (DATAPTR),Y
  452.           STA LENGTH
  453.           INY
  454.           LDA (DATAPTR),Y
  455.           STA LENGTH+1
  456.           INY
  457.           JMP LOADFILE   ; Now go move file into memory
  458. APLSOFT   LDA TXTTAB     ; Start of Applesoft program
  459.           STA DESTPTR
  460.           LDA TXTTAB+1
  461.           STA DESTPTR+1
  462.           LDY #0         ; Location of file length
  463.           LDA (DATAPTR),Y
  464.           STA LENGTH
  465.           INY
  466.           LDA (DATAPTR),Y
  467.           STA LENGTH+1
  468.           INY
  469.  
  470. * Load the file into memory
  471.  
  472. LOADFILE  LDX #0         ; No pre-index needed
  473.           LDA (DATAPTR),Y ; Get byte of file
  474.           STA (DESTPTR,X) ; Store it in memory
  475.           INC DESTPTR
  476.           BNE NOINC
  477.           INC DESTPTR+1
  478. NOINC     SEC            ; For subtraction
  479.           LDA LENGTH
  480.           SBC #1
  481.           STA LENGTH
  482.           LDA LENGTH+1
  483.           SBC #0
  484.           STA LENGTH+1
  485.           BNE CONT       ;  Check if LENGTH = 0
  486.           LDA LENGTH
  487.           BEQ DONE       ;  Finished loading file!
  488. CONT      INY            ; Move to next sector?
  489.           BNE LOADFILE   ; Still in same sector
  490.           LDY YTEMP      ; Get back T/S index
  491.           LDA (TSPTR),Y  ; Next track
  492.           STA TRACK
  493.           INY
  494.           LDA (TSPTR),Y  ; Next sector
  495.           STA SECTOR
  496.           INY
  497.           STY YTEMP
  498.           CLC            ; Load into data buffer
  499.           JSR READTS     ; Get next sector
  500.           LDY YTEMP      ; Should next T/S be loaded?
  501.           BNE SAMETS     ; No, keep this T/S list
  502.           LDY #2         ; Yes, get linking track, sector
  503.           LDA (TSPTR),Y  ; Link track
  504.           STA TRACK
  505.           INY
  506.           LDA (TSPTR),Y  ; Link sector
  507.           STA SECTOR
  508.           LDY #$0C       ; Next file sector
  509.           STY YTEMP
  510.           SEC            ; Load into T/S buffer
  511.           JSR READTS     ; Get next T/S list
  512. SAMETS    LDY #0
  513.           JMP LOADFILE   ; Continue loading file
  514.  
  515. * Done loading!  Finish up Applesoft load.
  516.  
  517. DONE      LDA CMD
  518.           BNE GOODEXIT   ; DBLOAD, so all is done
  519.           LDA DESTPTR    ; Tell Applesoft where prgm ends
  520.           STA PRGEND
  521.           LDA DESTPTR+1
  522.           STA PRGEND+1
  523.           INC DESTPTR
  524.           BNE NOINC2
  525.           INC DESTPTR+1
  526. NOINC2    LDA DESTPTR    ; Also set beginning of simple
  527.           STA VARTAB     ;  variable space at end of
  528.           LDA DESTPTR+1  ;  program
  529.           STA VARTAB+1
  530. GOODEXIT  CLC            ; No errors
  531.           RTS            ; Return to BASIC.SYSTEM
  532.  
  533. * Catalog DOS 3.3 disk
  534.  
  535. EXECAT    JSR SETPARMS   ; Set up MLI parameters
  536.           JSR CHECKPRO   ; Check for ProDOS disk
  537.           LDA #3         ; Set # parms for READ_BLOCK
  538.           STA PARMTBL
  539.           JSR CROUT
  540.           LDA #$11       ; Track of directory
  541.           STA TRACK
  542.           LDA #$0F       ; Sector of directory
  543.           STA SECTOR
  544.           LDA #0         ; To keep track of # listed,
  545.           STA DESTPTR    ; DESTPTR temp. used
  546. NEXTSEC   CLC            ; Load into DATA buffer
  547.           JSR READTS
  548.           LDA #$0B       ; First entry in directory
  549.           STA DATAPTR
  550. NXTFILE   LDY #0         ; Track of file data
  551.           LDA (DATAPTR),Y ; = $FF if deleted
  552.           BNE CHKDEL     ; Not end of directory
  553.           LDY #3
  554.           LDA (DATAPTR),Y
  555.           BEQ DONECAT    ; If first name chr=0, then done
  556. CHKDEL    CMP #$FF       ; Is file deleted?
  557.           BEQ SKIPDEL    ;  Don't list if deleted
  558.           LDX #" "       ; Assume file unlocked
  559.           LDY #2         ; Position of file type, lock
  560.           LDA (DATAPTR),Y ; Is file locked?
  561.           BPL NOLOCK     ; No, print space
  562.           LDX #"*"       ; Yes, print asterisk
  563. NOLOCK    TXA
  564.           JSR COUT       ; Print lock status
  565.           LDA (DATAPTR),Y
  566.           AND #$0F       ; Ignore lock, unknown types
  567.           TAX
  568.           LDA TYPESYMB,X ; Symbol to display (T,I,A,B)
  569.           JSR COUT
  570.           LDA #" "
  571.           JSR COUT
  572.           LDY #$21       ; Position of file size (sectors)
  573.           LDA (DATAPTR),Y
  574.           JSR PRNTSIZE   ; Convert to decimal and display
  575.           LDA #" "
  576.           JSR COUT
  577.           LDY #3         ; Beginning of file name
  578. PRNTNAME  LDA (DATAPTR),Y ; Get character of name
  579.           BEQ DONENAME   ; If zero, then name is finished
  580.           JSR COUT       ; Print the character
  581.           INY
  582.           CPY #$21       ; Max filename length 30 characters
  583.           BCC PRNTNAME
  584. DONENAME  JSR CROUT
  585.           INC DESTPTR    ; Check if 20 names listed
  586.           LDA DESTPTR
  587.           CMP #20
  588.           BNE SKIPDEL    ; Continue of not 20
  589. CHKEY     LDA KBD        ; Wait for keypress
  590.           BPL CHKEY      ; No keypress
  591.           BIT KBSTROBE   ; Clear key pressed status
  592.           CMP #$83       ; CTRL-C?
  593.           BEQ DONECAT    ; Yes, halt catalog
  594.           LDA #0         ; Reset # cataloged to 0
  595.           STA DESTPTR
  596. SKIPDEL   CLC
  597.           LDA DATAPTR    ; Move to next entry
  598.           ADC #$23
  599.           STA DATAPTR
  600.           BCC NXTFILE    ; Continue in this directory
  601.           LDY #1         ; Track of next directory
  602.           LDA (DATAPTR),Y
  603.           STA TRACK
  604.           INY            ; Sector of next directory
  605.           LDA (DATAPTR),Y
  606.           BEQ DONECAT    ; If zero, then CAT is done
  607.           STA SECTOR
  608.           JMP NEXTSEC
  609.  
  610. * Done with DCAT! Clean up the mess...
  611.  
  612. DONECAT   JSR CROUT
  613.           CLC            ; No errors
  614.           RTS            ; Ride off into the sunset
  615.  
  616. * Find filename and save it
  617.  
  618. GETNAME   LDA IN,X       ; Get next character
  619.           CMP #$A0       ; Is it blank?
  620.           BNE GTNM2      ; No, part of file name
  621.           INX
  622.           BNE GETNAME    ; Always branch
  623. GTNM2     LDY #0
  624. GTNM3     LDA IN,X       ; Get character
  625.           CMP #$8D       ; End of command?
  626.           BEQ GOTNAME
  627.           CMP #","       ; End of file name?
  628.           BEQ GOTNAME
  629.           STA FILENAME,Y
  630.           INY
  631.           INX
  632.           BNE GTNM3      ; Always branch
  633. GOTNAME   STY FLNMLEN    ; Store length of file name
  634.           DEX            ; Save command + name length so
  635.           STX XLEN       ; ProDOS ignores DOS filename
  636.           RTS
  637.  
  638. * Convert track/sector into block and load it
  639.  
  640. READTS    PHP            ; Save carry flag for later
  641.           LDA HIMEM      ; Find buffer to load to
  642.           STA BUFFER
  643.           LDA HIMEM+1
  644.           BCS TSBUF      ; Skip next if for T/S buffer
  645.           ADC #2         ; Set buffer to DATA buffer
  646. TSBUF     STA BUFFER+1
  647.           LDA TRACK
  648.           ASL            ; Multiply track # by 8
  649.           ASL
  650.           ASL
  651.           STA BLOCK
  652.           LDA #0
  653.           STA BLOCK+1
  654.           ROL BLOCK+1    ; Shift carry bit into BLOCK+1
  655.           LDY SECTOR     ; Find relative block number
  656.           LDA RELBLOCK,Y ; containing desired sector
  657.           CLC
  658.           ADC BLOCK      ; Add relative block to base
  659.           STA BLOCK
  660.           JSR MLI
  661.           DFB $80        ; READ_BLOCK
  662.           DA PARMTBL
  663.           BCS READERR    ; Bad news if carry set
  664.           LDY SECTOR     ; Find half of block to read
  665.           LDA BLKHALF,Y  ;  contains sector
  666.           PLP            ; Recover carry flag
  667.           BCC DTBUF      ; If clear, set up DATAPTR
  668.           CLC
  669.           ADC BUFFER+1
  670.           STA TSPTR+1
  671.           LDA #0
  672.           STA TSPTR
  673.           BEQ READDONE
  674. DTBUF     ADC BUFFER+1
  675.           STA DATAPTR+1
  676.           LDA #0
  677.           STA DATAPTR
  678. READDONE  RTS
  679.  
  680. READERR   PLA            ; Pop return addr, status
  681.           PLA
  682.           PLA
  683.           LDA #8         ; Other erros reported as
  684.           SEC            ;  BASIC.SYSTEM I/O ERROR
  685.           RTS
  686.  
  687. * Set parameters for READ_BLOCK command
  688.  
  689. SETPARMS  LDA SPARM      ; Get slot specified
  690.           ASL            ; Slot * 16
  691.           ASL
  692.           ASL
  693.           ASL
  694.           LDX DPARM      ; Get drive specified
  695.           CPX #2         ; Drive 2?
  696.           BNE SAVEUNIT
  697.           ORA #$80       ; Set bit for drive 2
  698. SAVEUNIT  STA UNITNUM    ; Store slot/drive as unit #
  699.           RTS
  700.  
  701. * Make sure disk is not ProDOS disk
  702.  
  703. CHECKPRO  LDA #2         ; Set # parms for ON_LINE
  704.           STA PARMTBL
  705.           LDA #<IN
  706.           STA BUFFER
  707.           LDA #>IN
  708.           STA BUFFER+1
  709.           JSR MLI        ; Do ON_LINE command
  710.           DFB $C5        ; Code for ON_LINE
  711.           DA PARMTBL
  712.           CMP #$52       ; MLI error: not ProDOS disk
  713.           BEQ NOPRO      ; That's what we want!
  714.           TAX            ; Save error code in X
  715.           PLA            ; Pop off return addr from stack
  716.           PLA
  717.           LDA #3         ; Assume error; no device
  718.           CPX #$28       ; MLI error: no device
  719.           BEQ SKIPIO     ; If no device, don't print I/O
  720.           LDA #8         ; Other error, flag as I/O error
  721. SKIPIO    SEC
  722. NOPRO     RTS            ; Return to BASIC or command
  723.  
  724. * Convert filesize to decimal and display it
  725.  
  726. PRNTSIZE  TAX            ; Copy filesize to X-reg
  727.           LDA #"0"       ; Load Acc with ASCII 0
  728.           CPX #100       ; Is it greater than 100?
  729.           BCS NOZERO     ; Yes, don't print leading zeros
  730.           CPX #10        ; Is it greater than 10?
  731.           BCS ONEZERO    ; Yes, only one leading zero
  732.           JSR COUT       ; Print 1 of 2 leading zeros
  733. ONEZERO   JSR COUT       ; Print a leading 0
  734.  
  735. * LINPRT converts hex number in X-reg (low) and
  736. * Acc (high) into decimal number and displays it,
  737. * therefore Acc must be 0 and X-reg is filesize
  738.  
  739. NOZERO    LDA #0
  740.           JMP LINPRT     ; Display filesize
  741.  
  742. * relative block numbers for sector computations
  743.  
  744. RELBLOCK  DFB 0,7,6,6,5,5,4,4
  745.           DFB 3,3,2,2,1,1,0,7
  746.  
  747. * Locate half of block containing sector
  748.  
  749. BLKHALF   DFB 0,0,1,0,1,0,1,0
  750.           DFB 1,0,1,0,1,0,1,1
  751.  
  752. * Filetype symbols
  753.  
  754. TYPESYMB  ASC "TIA B           " ; 11 spaces after B
  755.  
  756. * Command names
  757.  
  758. DLNAME    ASC "DLOAD"
  759. DLLEN     EQU *
  760. DBNAME    ASC "DBLOAD"
  761. DBLEN     EQU *
  762. DCNAME    ASC "DCAT"
  763. DCLEN     EQU *
  764.  
  765. END       EQU *
  766. END100    EQU END+$100   ; For relocating routine
  767.